﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using hedefgrup.reports.renault.database;

namespace hedefgrup.reports.common
{
    public class Report_DealerAnalysis : Report_Abstract
    {
        internal class Storage
        {
            Dictionary<string, float> _Storage = new Dictionary<string, float>();

            internal List<string> Subjects = new List<string>();
            internal IDictionary<string, string> SubjectDealers = new Dictionary<string, string>();
            internal IDictionary<string, string> SubjectTCKN = new Dictionary<string, string>();

            internal void Increment(string subjectCode, string subjectTCKN, string dealerCode, string questionCode, string[] optionCodes, bool incrementDealerCount, bool incrementQuestionCount)
            {
                foreach (String optionCode in optionCodes)
                {
                    Increment(subjectCode, subjectTCKN, dealerCode, questionCode, optionCode.Trim(), incrementDealerCount, incrementQuestionCount);
                    incrementDealerCount = false;
                    incrementQuestionCount = false;
                }
            }

            internal float Get(string subjectCode, string questionCode, string optionCode)
            {
                if (!string.IsNullOrEmpty(subjectCode) && !string.IsNullOrEmpty(questionCode) && !string.IsNullOrEmpty(optionCode))
                {
                    if (_Storage.ContainsKey(subjectCode + questionCode + optionCode))
                    {
                        return _Storage[subjectCode + questionCode + optionCode];
                    }
                }
                return 0f;
            }

            internal float Get(string subjectCode, string questionCode)
            {
                if (!string.IsNullOrEmpty(subjectCode) && !string.IsNullOrEmpty(questionCode))
                {
                    if (_Storage.ContainsKey(subjectCode + questionCode))
                    {
                        return _Storage[subjectCode + questionCode];
                    }
                }
                return 0f;
            }

            internal float Get(string subjectCode)
            {
                if (!string.IsNullOrEmpty(subjectCode))
                {
                    if (_Storage.ContainsKey(subjectCode))
                    {
                        return _Storage[subjectCode];
                    }
                }
                return 0f;
            }

            internal string GetSubjectDealer(string subjectCode)
            {
                if (SubjectDealers.ContainsKey(subjectCode))
                {
                    return SubjectDealers[subjectCode];
                }
                else
                {
                    return null;
                }
            }

            internal string GetSubjectTCKN(string subjectCode)
            {
                if (SubjectTCKN.ContainsKey(subjectCode))
                {
                    return SubjectTCKN[subjectCode];
                }
                else
                {
                    return null;
                }
            }

            internal void Increment(string subjectCode, string subjectTCKN, string dealerCode, string questionCode, string optionCode, bool incrementDealerCount, bool incrementQuestionCount)
            {
                if (!string.IsNullOrEmpty(subjectCode) && !string.IsNullOrEmpty(questionCode) && !string.IsNullOrEmpty(optionCode))
                {
                    subjectCode = subjectCode.Trim();
                    dealerCode = dealerCode.Trim();

                    if (!Subjects.Contains(subjectCode))
                    {
                        Subjects.Add(subjectCode);
                        SubjectDealers.Add(subjectCode, dealerCode);
                        SubjectTCKN.Add(subjectCode, subjectTCKN);
                    }

                    if (_Storage.ContainsKey(subjectCode + questionCode + optionCode))
                    {
                        _Storage[subjectCode + questionCode + optionCode]++;
                        if (incrementDealerCount)
                        {
                            _Storage[subjectCode]++;
                        }
                        if (incrementQuestionCount)
                        {
                            _Storage[subjectCode + questionCode]++;
                        }
                    }
                    else
                    {
                        _Storage.Add(subjectCode + questionCode + optionCode, 1f);

                        if (incrementDealerCount)
                        {
                            if (_Storage.ContainsKey(subjectCode))
                            {
                                _Storage[subjectCode]++;
                            }
                            else
                            {
                                _Storage.Add(subjectCode, 1f);
                            }
                        }

                        if (incrementQuestionCount)
                        {
                            if (_Storage.ContainsKey(subjectCode + questionCode))
                            {
                                _Storage[subjectCode + questionCode]++;
                            }
                            else
                            {
                                _Storage.Add(subjectCode + questionCode, 1f);
                            }
                        }

                    }
                }
            }
        }

        protected override void SetCriteriaList()
        {
            Criterias.Add(new Criteria_Roll() { Context = Context });
            Criterias.Add(new Criteria_EndMonth() { Context = Context });
            Criterias.Add(new Criteria_Network() { Context = Context });
            Criterias.Add(new Criteria_Organization() { Context = Context });
        }

        private string[] QuestionList
        {
            get
            {
                if (Context.CompatibleProjectName == Global.PROJECT_QVN2013)
                {
                    return new string[] { "S18", "S17", "S17a" };
                }
                else
                {
                    if (base.GetAuthLevel() == "coordinator" || base.GetAuthLevel() == "dealer")
                    {
                        return new string[] { "S2", "S4_1", "S4", "S4_1_S41_1=CASE WHEN S4 = 1 OR S4_1 = 1 THEN 1 ELSE 2 END", "S6", "S7", "S7A", "S8", "S8b" };
                    }
                    else
                    {
                        return new string[] { "S2", "S3b", "S4_1", "S4", "S4_1_S41_1=CASE WHEN S4 = 1 OR S4_1 = 1 THEN 1 ELSE 2 END", "S6", "S6_2", "S7", "S7A", "S8", "S8b", "S11", "S12" };
                    }
                }
            }
        }

        private void ProcessRow(DataRow reportRow, Storage storage)
        {
            string dealerCode = reportRow[base.DealerColumn].ToString();
            string subjectCode = reportRow["SUBJECT"].ToString();
            string coordinatorCode = CoordinatorsReported ? "XDISPLAYLATER_" + reportRow["KOORDINATOR"].ToString().Substring(12, 3) : string.Empty;
            string areaCode = "YDISPLAYLATER_" + reportRow[AreaColumn].ToString().Substring(6, 1);

            string[] questionList = QuestionList;

            bool incrementDealerCount = true;

            foreach (string question in questionList)
            {
                string columnName = question.IndexOf('=') > 0 ? question.Substring(0, question.IndexOf('=')) : question;
                storage.Increment("_TOTAL", reportRow["SATICI_TCKN"].ToString(), "_TOTAL", columnName, reportRow[columnName].ToString().Split(','), incrementDealerCount, true);
                incrementDealerCount = false;
            }

            incrementDealerCount = true;

            foreach (string question in questionList)
            {
                string columnName = question.IndexOf('=') > 0 ? question.Substring(0, question.IndexOf('=')) : question;
                storage.Increment(subjectCode, reportRow["SATICI_TCKN"].ToString(), dealerCode, columnName, reportRow[columnName].ToString().Split(','), incrementDealerCount, true);
                incrementDealerCount = false;
            }

            if (CoordinatorsReported)
            {
                incrementDealerCount = true;
                foreach (string question in questionList)
                {
                    string columnName = question.IndexOf('=') > 0 ? question.Substring(0, question.IndexOf('=')) : question;
                    storage.Increment(coordinatorCode, reportRow["SATICI_TCKN"].ToString(), coordinatorCode, columnName, reportRow[columnName].ToString().Split(','), incrementDealerCount, true);
                    incrementDealerCount = false;
                }
            }

            if (AreasReported)
            {
                incrementDealerCount = true;
                foreach (string question in questionList)
                {
                    string columnName = question.IndexOf('=') > 0 ? question.Substring(0, question.IndexOf('=')) : question;
                    storage.Increment(areaCode, reportRow["SATICI_TCKN"].ToString(), areaCode, columnName, reportRow[columnName].ToString().Split(','), incrementDealerCount, true);
                    incrementDealerCount = false;
                }
            }

            if (reportRow["FLOP"] != DBNull.Value && Convert.ToBoolean(reportRow["FLOP"]))
            {
                incrementDealerCount = true;
                foreach (string question in questionList)
                {
                    string columnName = question.IndexOf('=') > 0 ? question.Substring(0, question.IndexOf('=')) : question;
                    storage.Increment("_XFLOP", reportRow["SATICI_TCKN"].ToString(), "_XFLOP", columnName, reportRow[columnName].ToString().Split(','), incrementDealerCount, true);
                    incrementDealerCount = false;
                }
            }

            if (reportRow["SUBE"] != DBNull.Value && Convert.ToBoolean(reportRow["SUBE"]))
            {
                incrementDealerCount = true;
                foreach (string question in questionList)
                {
                    string columnName = question.IndexOf('=') > 0 ? question.Substring(0, question.IndexOf('=')) : question;
                    storage.Increment("_YBRANCH", reportRow["SATICI_TCKN"].ToString(), "_YBRANCH", columnName, reportRow[columnName].ToString().Split(','), incrementDealerCount, true);
                    incrementDealerCount = false;
                }
            }

            if (reportRow["SUBE"] == DBNull.Value && reportRow["BAGLINOKTA"] == DBNull.Value)
            {
                incrementDealerCount = true;
                foreach (string question in questionList)
                {
                    string columnName = question.IndexOf('=') > 0 ? question.Substring(0, question.IndexOf('=')) : question;
                    storage.Increment("_Z_S1_NO_BRANCH", reportRow["SATICI_TCKN"].ToString(), "_Z_S1_NO_BRANCH", columnName, reportRow[columnName].ToString().Split(','), incrementDealerCount, true);
                    incrementDealerCount = false;
                }
            }
        }

        protected virtual string ReportSubjectColumn
        {
            get
            {
                return base.DealerColumn;
            }
        }

        protected virtual string ReportSubjectHeader
        {
            get
            {
                return "Bayii Kodu";
            }
        }

        protected virtual DataTable GetReportData()
        {
            return db.query
            (
                "SELECT " + base.DealerColumn + ", " + ReportSubjectColumn + " AS SUBJECT, SATICI_TCKN, KOORDINATOR, " + base.AreaColumn + ", " + String.Join(",", QuestionList) + ",SUBE,FLOP,BAGLINOKTA FROM " + Context.TableName + " " +
                GetSqlStatementFilter(),
                base.GetSqlStatementParameters()
            );
        }

        public override ReportResult GenerateReport()
        {
            ReportResult results = new ReportResult(this);

            DataTable reportData = GetReportData();

            Storage storage = new Storage();

            foreach (DataRow reportRow in reportData.Rows)
            {
                ProcessRow(reportRow, storage);
            }

            Row headerRow = new Row();
            results.HeaderRows.Add(headerRow);

            headerRow.Cells.Add(new Cell() { Text = ReportSubjectHeader });

            if (ReportSubjectColumn != DealerColumn)
            {
                headerRow.Cells.Add(new Cell() { Text = "TCKN" });
                headerRow.Cells.Add(new Cell() { Text = "Bayii Kodu" });
            }

            headerRow.Cells.Add(new Cell() { Text = "Bayii Adı" });

            headerRow.Cells.Add(new Cell() { Text = "Baz" });

            if (Context.CompatibleProjectName == Global.PROJECT_SATIS_SUREC && ReportSubjectColumn == DealerColumn)
            {
                headerRow.Cells.Add(new Cell() { Text = "Ağırlıklı Skor" });
            }

            foreach (string question in QuestionList)
            {
                string columnName = question.IndexOf('=') > 0 ? question.Substring(0, question.IndexOf('=')) : question;
                Tree questionTree = Context.Questionnaire.Select(columnName)[0];
                if (Context.CompatibleProjectName == Global.PROJECT_SATIS_SUREC && columnName == "S8")
                {
                    headerRow.Cells.Add(new Cell() { Text = columnName + " - " + questionTree.Text, Span = 2 });
                }
                else
                {
                    headerRow.Cells.Add(new Cell() { Text = columnName + " - " + questionTree.Text, Span = questionTree.Children.Count });
                }
            }

            if (Context.CompatibleProjectName == Global.PROJECT_QVN2013)
            {
                headerRow.Cells.Add(new Cell() { Text = "Resmi Evrak Dönüşü Genel" });
                headerRow.Cells.Add(new Cell() { Text = "Arıza Dönüşü Genel" });
                headerRow.Cells.Add(new Cell() { Text = "Ek Aksesuar Dönüşü Genel" });
                headerRow.Cells.Add(new Cell() { Text = "Başka Neden Dönüşü Genel" });
                headerRow.Cells.Add(new Cell() { Text = "Açıklamalar Dönüşü Genel" });
                headerRow.Cells.Add(new Cell() { Text = "Aksesuar Teslim Dönüşü Genel" });
            }

            Row optionsRow = new Row();
            results.HeaderRows.Add(optionsRow);

            optionsRow.Cells.Add(new Cell());

            optionsRow.Cells.Add(new Cell());

            optionsRow.Cells.Add(new Cell());

            if (Context.CompatibleProjectName == Global.PROJECT_SATIS_SUREC && ReportSubjectColumn == DealerColumn)
            {
                optionsRow.Cells.Add(new Cell());
            }

            if (ReportSubjectColumn != DealerColumn)
            {
                optionsRow.Cells.Add(new Cell());
                optionsRow.Cells.Add(new Cell());
            }

            foreach (string question in QuestionList)
            {
                string columnName = question.IndexOf('=') > 0 ? question.Substring(0, question.IndexOf('=')) : question;
                Tree questionTree = Context.Questionnaire.Select(columnName)[0];
                if (Context.CompatibleProjectName == Global.PROJECT_SATIS_SUREC && columnName == "S8")
                {
                    optionsRow.Cells.Add(new Cell() { Text = "Ortalama" });
                    optionsRow.Cells.Add(new Cell() { Text = "9/10 Puan" });
                }
                else
                {
                    foreach (Tree optionTree in questionTree.Children)
                    {
                        optionsRow.Cells.Add(new Cell() { Text = optionTree.Key + "-" + optionTree.Text });
                    }
                }
            }

            if (Context.CompatibleProjectName == Global.PROJECT_QVN2013)
            {
                optionsRow.Cells.Add(new Cell());
                optionsRow.Cells.Add(new Cell());
                optionsRow.Cells.Add(new Cell());
                optionsRow.Cells.Add(new Cell());
                optionsRow.Cells.Add(new Cell());
                optionsRow.Cells.Add(new Cell());
            }

            storage.Subjects.Sort();

            foreach (string subjectCode in storage.Subjects)
            {
                Row reportRow = new Row();
                results.Rows.Add(reportRow);

                switch (subjectCode)
                {
                    case "_TOTAL":

                        if (ReportSubjectColumn != DealerColumn)
                        {
                            reportRow.Cells.Add(new Cell() { });
                            reportRow.Cells.Add(new Cell() { });
                            reportRow.Cells.Add(new Cell() { Text = "GNL" });
                        }
                        else
                        {
                            reportRow.Cells.Add(new Cell() { Text = "GNL" });
                        }
                        reportRow.Cells.Add(new Cell() { Text = "Genel", TextAlign = "left" });
                        break;
                    case "_XFLOP":
                        if (ReportSubjectColumn != DealerColumn)
                        {
                            reportRow.Cells.Add(new Cell() { });
                            reportRow.Cells.Add(new Cell() { });
                            reportRow.Cells.Add(new Cell() { Text = "FG" });
                        }
                        else
                        {
                            reportRow.Cells.Add(new Cell() { Text = "FG" });
                        }
                        reportRow.Cells.Add(new Cell() { Text = "Flop Geneli", TextAlign = "left" });
                        break;
                    case "_YBRANCH":
                        if (ReportSubjectColumn != DealerColumn)
                        {
                            reportRow.Cells.Add(new Cell() { });
                            reportRow.Cells.Add(new Cell() { });
                            reportRow.Cells.Add(new Cell() { Text = "SBG" });
                        }
                        else
                        {
                            reportRow.Cells.Add(new Cell() { Text = "SBG" });
                        }
                        reportRow.Cells.Add(new Cell() { Text = "Şube Geneli", TextAlign = "left" });
                        break;
                    case "_Z_S1_NO_BRANCH":
                        if (ReportSubjectColumn != DealerColumn)
                        {
                            reportRow.Cells.Add(new Cell() { });
                            reportRow.Cells.Add(new Cell() { });
                            reportRow.Cells.Add(new Cell() { Text = "S-1" });
                        }
                        else
                        {
                            reportRow.Cells.Add(new Cell() { Text = "S-1" });
                        }
                        reportRow.Cells.Add(new Cell() { Text = "Şebeke 1 Geneli 2", TextAlign = "left" });
                        break;
                    default:
                        string subjectCodeForDisplay = subjectCode.Replace("XDISPLAYLATER_", "").Replace("YDISPLAYLATER_", "");
                        string subjectDealer = storage.GetSubjectDealer(subjectCode).Replace("XDISPLAYLATER_", "").Replace("YDISPLAYLATER_", "");
                        if (ReportSubjectColumn != DealerColumn)
                        {
                            reportRow.Cells.Add(new Cell() { Text = subjectCode });
                            reportRow.Cells.Add(new Cell() { Text = storage.GetSubjectTCKN(subjectCode) });
                            reportRow.Cells.Add(new DealerCodeCell() { Text = storage.GetSubjectDealer(subjectCode) });
                        }
                        else
                        {
                            reportRow.Cells.Add(new DealerCodeCell() { Text = subjectCodeForDisplay });
                        }
                        reportRow.Cells.Add(new Cell() { Text = GetDealerName(subjectDealer), TextAlign = "left" });
                        break;
                }

                reportRow.Cells.Add(new Cell() { Text = storage.Get(subjectCode).ToString() });

                if (Context.CompatibleProjectName == Global.PROJECT_SATIS_SUREC && ReportSubjectColumn == DealerColumn)
                {
                    // TODO: Include S4_1 in calculation
                    float testDrive_15 = (storage.Get(subjectCode, "S4", "1") + storage.Get(subjectCode, "S4_1", "1")) / storage.Get(subjectCode, "S4_1");
                    float customerCall_15 = storage.Get(subjectCode, "S7", "1") / storage.Get(subjectCode, "S7");
                    float explanationsSatisfaction_20 = storage.Get(subjectCode, "S6", "1") / storage.Get(subjectCode, "S6");
                    float salesPersonSatisfaction_50 = (storage.Get(subjectCode, "S8", "10") + storage.Get(subjectCode, "S8", "9")) / storage.Get(subjectCode, "S8");

                    // XXX
                    float overallWeightedScore =
                        testDrive_15 * 0.40f +
                        customerCall_15 * 0.20f +
                        // explanationsSatisfaction_20 * 0.2f +
                        salesPersonSatisfaction_50 * 0.40f;

                    reportRow.Cells.Add(new Cell() { Text = string.Format("{0:0.00}", 100 * overallWeightedScore), Bold = true });
                }

                foreach (string question in QuestionList)
                {
                    string columnName = question.IndexOf('=') > 0 ? question.Substring(0, question.IndexOf('=')) : question;
                    float s18Count = storage.Get(subjectCode, columnName);
                    Tree questionTree = Context.Questionnaire.Select(columnName)[0];
                    if (Context.CompatibleProjectName == Global.PROJECT_SATIS_SUREC && columnName == "S8")
                    {
                        float totalValue = 0;
                        foreach (Tree optionTree in questionTree.Children)
                        {
                            totalValue += storage.Get(subjectCode, columnName, optionTree.Key) * Convert.ToInt32(optionTree.Key);
                        }
                        reportRow.Cells.Add(new Cell() { Text = string.Format("{0:0.00}", s18Count > 0 ? (totalValue / s18Count) : 0f) });
                        float value = storage.Get(subjectCode, columnName, "9") + storage.Get(subjectCode, columnName, "10");
                        reportRow.Cells.Add(new Cell() { Text = string.Format("{0:0.0}", s18Count > 0 ? 100 * (value / s18Count) : 0f) });
                    }
                    else
                    {
                        foreach (Tree optionTree in questionTree.Children)
                        {
                            float value = storage.Get(subjectCode, columnName, optionTree.Key);
                            reportRow.Cells.Add(new Cell() { Text = string.Format("{0:0.0}", s18Count > 0 ? 100 * (value / s18Count) : 0f) });
                        }
                    }
                }

                if (Context.CompatibleProjectName == Global.PROJECT_QVN2013)
                {
                    AddPercentageOfOptionInBaseForSubject(storage, reportRow, subjectCode, "S17a", "1");
                    AddPercentageOfOptionInBaseForSubject(storage, reportRow, subjectCode, "S17a", "2");
                    AddPercentageOfOptionInBaseForSubject(storage, reportRow, subjectCode, "S17a", "3");
                    AddPercentageOfOptionInBaseForSubject(storage, reportRow, subjectCode, "S17a", "4");
                    AddPercentageOfOptionInBaseForSubject(storage, reportRow, subjectCode, "S17a", "5");
                    AddPercentageOfOptionInBaseForSubject(storage, reportRow, subjectCode, "S17a", "6");
                }
            }

            return results;
        }

        private void AddPercentageOfOptionInBaseForSubject(Storage storage, Row reportRow, string subjectCode, string questionCode, string optionCode)
        {
            float qo_Count = storage.Get(subjectCode, questionCode, optionCode);
            float qo_Value = 100 * (qo_Count / storage.Get(subjectCode));
            string qo_Color = qo_Value <= Global.TRESHOLD_FAILUR_CALL_DEALER_RENAULT ? "Green" : "Red";
            reportRow.Cells.Add(new Cell() { Text = string.Format("{0:0.0}", qo_Value), Color = qo_Color });
        }

        public override string DisplayName
        {
            get { return "Bayii Analiz"; }
        }

        public override bool SupportsProject(string projectName)
        {
            return base.SupportsProject(projectName) || projectName == Global.PROJECT_SATIS_SUREC;
        }

        public override string SortPrefix
        {
            get { return "0x04"; }
        }
    }
}
